Prediksi Harga Rumah
Pendahuluan
Seperti yang kita ketahui, harga rumah cenderung sangat beragam, ada yang relatif sangat mahal ataupun murah. Pada kenyataannya kita sulit menentukan seberapa besar harga rumah berdasarkan berbagai fitur-fitur atau fasilitas yang ada di dalam rumah. Kadang ada sebuah rumah yang memiliki luas lebih kecil dan sedikit kamar mandi dan sebagainya tetapi harganya relatif lebih mahal karena terletak di kota yang berbeda. Oleh karena itu, pada kesempatan ini saya mencoba membangun model yang dapat memprediksi harga rumah berdasarkan beberapa informasi fitur-fitur atau fasilitas yang ada dalam rumah alias menggunakan prediktor. Saya membangun model ini menggunakan dataset dari kaggle berikut.
Persiapan dan Wrangling Data
Pustaka
library(tidyverse)
library(caTools)
library(GGally)
library(ggplot2)
library(plotly)
library(rsample)
library(MLmetrics)
library(lmtest)
library(car)Membaca Dataset
house <- read.csv("HousePrices_HalfMil.csv")
houseDeskripsi Kolom :
Area: Luas rumah atau bangunan.Garage: Jumlah Garasi pada rumah.FirePlace: Jumlah tempat perapian.Baths: Jumlah Kamar mandi.White.Marble: Apakah menggunakan marmer putih; 1 (ya) ; 0 (tidak).Black.Marble: Apakah menggunakan marmer hitam; 1 (ya) ; 0 (tidak).Indian.Marble: Apakah menggunakan marmer India; 1 (ya) ; 0 (tidak).Floors: Apakah menggunakan keramik; 1 (ya) ; 0 (tidak).City: Terletak di kota mana (Terdapat kategori 3, 2, 1)Solar: Apakah menggunakan panel surya; 1 (ya) ; 0 (tidak).Electric: Apakah menggunakan Electric ; 1 (ya) ; 0 (tidak).Fiber: Apakah menggunakan Fiber ; 1 (ya) ; 0 (tidak).Glass.Doors: Apakah terdapat Glass Doors ; 1 (ya) ; 0 (tidak).Swiming.Pool: Apakah terdapat Swiming Pool ; 1 (ya) ; 0 (tidak).Garden: Apakah terdapat Taman ; 1 (ya) ; 0 (tidak).Prices: Harga rumah.
Mengecek Nilai Hilang
anyNA(house)#> [1] FALSE
Tidak ada data yang hilang (missing value) sehingga kita dapat melanjutkan ke tahap selanjutnya.
Mengecek Duplikasi Data
anyDuplicated(house)#> [1] 4416
Ternyata terdapat data yang terduplikasi sehingga sebaiknya kita menghapus data duplikasi tersebut dengan fungsi distinct()
house <- house %>% distinct()
anyDuplicated(house)#> [1] 0
Asumsi Linearitas
ggcorr(data = house, label = T, hjust = 1, layout.exp = 3)Variabel
Indian.Marble,Black.Marble,White.Marblememiliki hubungan yang saling mempengaruhi sehingga sebaiknya memilih salah satu variabel aja agar tidak menghasilkan model redundan.Variabel yang memiliki korelasi yang baik dengan kelas target (
Prices) adalahFloorsdanFiber.Terdapat pula variabel yang tidak memiliki hubungan dengan kelas target (Korelasinya = 0) yaitu
Garden,Swiming.PooldanSolar.
Mengecek Struktur Data
glimpse(house)#> Rows: 494,307
#> Columns: 16
#> $ Area <int> 164, 84, 190, 75, 148, 124, 58, 249, 243, 242, 61, 189, …
#> $ Garage <int> 2, 2, 2, 2, 1, 3, 1, 2, 1, 1, 2, 2, 2, 3, 3, 3, 1, 3, 2,…
#> $ FirePlace <int> 0, 0, 4, 4, 4, 3, 0, 1, 0, 2, 4, 0, 0, 3, 3, 4, 0, 3, 3,…
#> $ Baths <int> 2, 4, 4, 4, 2, 3, 2, 1, 2, 4, 5, 4, 2, 3, 1, 1, 5, 3, 5,…
#> $ White.Marble <int> 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,…
#> $ Black.Marble <int> 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1,…
#> $ Indian.Marble <int> 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,…
#> $ Floors <int> 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1,…
#> $ City <int> 3, 2, 2, 1, 2, 1, 3, 1, 1, 2, 1, 2, 1, 3, 3, 1, 3, 1, 3,…
#> $ Solar <int> 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0,…
#> $ Electric <int> 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1,…
#> $ Fiber <int> 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0,…
#> $ Glass.Doors <int> 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1,…
#> $ Swiming.Pool <int> 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0,…
#> $ Garden <int> 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0,…
#> $ Prices <int> 43800, 37550, 49500, 50075, 52400, 54300, 34400, 50425, …
Menyesuaikan Tipe Data
lapply(X = house[, 2:12],
FUN = unique)#> $Garage
#> [1] 2 1 3
#>
#> $FirePlace
#> [1] 0 4 3 1 2
#>
#> $Baths
#> [1] 2 4 3 1 5
#>
#> $White.Marble
#> [1] 0 1
#>
#> $Black.Marble
#> [1] 1 0
#>
#> $Indian.Marble
#> [1] 0 1
#>
#> $Floors
#> [1] 0 1
#>
#> $City
#> [1] 3 2 1
#>
#> $Solar
#> [1] 1 0
#>
#> $Electric
#> [1] 1 0
#>
#> $Fiber
#> [1] 1 0
Menghapus variable Black.Marble dan Indian.Marble untuk menghindari model redundan sehingga hanya menggunakan variable White.Marble karena variable ini dapat menghubungkan korelasi Black.Marble & Indian.Marble dengan Black.Marble & White.Marble.
Kita juga menyesuaikan tipe data factor untuk kolom yang memiliki nilai berulang.
house_clean <-
house %>%
select(-c(Black.Marble, Indian.Marble)) %>%
mutate(
Garage = as.factor(Garage),
FirePlace = as.factor(FirePlace),
Baths = as.factor(Baths),
White.Marble = as.factor(White.Marble),
Floors = as.factor(Floors),
City = as.factor(City),
Solar = as.factor(Solar),
Electric = as.factor(Electric),
Glass.Doors = as.factor(Glass.Doors),
Swiming.Pool = as.factor(Swiming.Pool),
Garden = as.factor(Garden),
Fiber = as.factor(Fiber)
) Eksplorasi Data Analisis
Persebaran Harga di Setiap Kota
box <-
ggplot(data = house_clean, aes(x = City, y = Prices)) +
geom_boxplot(aes(fill = City)) +
labs(title = "Persebaran Harga Rumah",
x = "City",
y = "Price",
fill = "City : ") +
theme_classic() +
theme(axis.text.x = element_blank())
ggplotly(box)Persebaran Luas Daerah di Setiap Kota
box_1 <-
ggplot(data = house_clean, aes(x = City, y = Area)) +
geom_boxplot(aes(fill = City)) +
labs(title = "Persebaran Luas Rumah",
x = "City",
y = "Luas",
fill = "City : ") +
theme_classic() +
theme(axis.text.x = element_blank())
ggplotly(box_1)Ringkasan Data
summary(house_clean)#> Area Garage FirePlace Baths White.Marble Floors
#> Min. : 1.0 1:164646 0:98448 1:99154 0:329720 0:247485
#> 1st Qu.: 63.0 2:164374 1:98851 2:98643 1:164587 1:246822
#> Median :125.0 3:165287 2:98810 3:99063
#> Mean :124.9 3:99057 4:98885
#> 3rd Qu.:187.0 4:99141 5:98562
#> Max. :249.0
#> City Solar Electric Fiber Glass.Doors Swiming.Pool
#> 1:164437 0:247812 0:246897 0:247005 0:247153 0:246965
#> 2:164969 1:246495 1:247410 1:247302 1:247154 1:247342
#> 3:164901
#>
#>
#>
#> Garden Prices
#> 0:246349 Min. : 7725
#> 1:247958 1st Qu.:33500
#> Median :41850
#> Mean :42047
#> 3rd Qu.:50750
#> Max. :77975
Secara umum, semua kolom prediktor bertipe factor cenderung memiliki proporsi kelas seimbang seperti Baths, Fiber, Garage dll, kecuali kolom White.Marble yang memiliki perbedaan signifikan antara ya (1) dan tidak (0).
Pemodelan
Pemisahan Dataset
set.seed(100) # merujuk pada key untuk proses CV knn
index <- sample(nrow(house_clean), nrow(house_clean)*0.8)
train_house <- house_clean[index, ]
test_house <- house_clean[-index, ]dim(train_house)#> [1] 395445 14
Data latih terdiri dari 395,445 baris dengan 14 kolom.
dim(test_house)#> [1] 98862 14
Data uji terdiri dari 98,862 baris dengan 14 kolom.
Simple Linear Regression
price_sm_model <- lm(formula = Prices ~ Floors, data = train_house)
summary(price_sm_model)#>
#> Call:
#> lm(formula = Prices ~ Floors, data = train_house)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -27205.4 -6980.4 -17.7 6582.3 28557.3
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 34542.71 21.36 1617.3 <0.0000000000000002 ***
#> Floors1 15012.71 30.23 496.6 <0.0000000000000002 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 9505 on 395443 degrees of freedom
#> Multiple R-squared: 0.3841, Adjusted R-squared: 0.3841
#> F-statistic: 2.466e+05 on 1 and 395443 DF, p-value: < 0.00000000000000022
Kita mencoba melihat performa model Simple Linear Regression dengan prediktor Floors karena merupakan prediktor yang memiliki korelasi terkuat. R-squared yang dihasilkan model ini relatif belum baik yaitu R-squared : 0.3841.
Prediktor Multiple Linear Regression
Kita ingin mencoba menemukan prediktor mana saja yang akan memberikan ukuran model terbaik dan memenuhi asumsi regresi linear.
Pertimbangan Pertama, Step Wise Regression
- Model Seluruh Prediktor
test_model <- lm(formula = Prices ~., data = train_house)
summary(test_model)#>
#> Call:
#> lm(formula = Prices ~ ., data = train_house)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -2544.75 -2486.92 0.85 2494.86 2545.43
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 9740.05740 15.76995 617.634 <0.0000000000000002 ***
#> Area 25.01828 0.04522 553.245 <0.0000000000000002 ***
#> Garage2 1501.24961 7.96115 188.572 <0.0000000000000002 ***
#> Garage3 3009.45209 7.95040 378.529 <0.0000000000000002 ***
#> FirePlace1 747.08307 10.28219 72.658 <0.0000000000000002 ***
#> FirePlace2 1488.65778 10.28461 144.746 <0.0000000000000002 ***
#> FirePlace3 2241.72986 10.27300 218.216 <0.0000000000000002 ***
#> FirePlace4 3002.37790 10.27634 292.164 <0.0000000000000002 ***
#> Baths2 1268.66047 10.26942 123.538 <0.0000000000000002 ***
#> Baths3 2499.63998 10.25427 243.766 <0.0000000000000002 ***
#> Baths4 3740.43721 10.26155 364.510 <0.0000000000000002 ***
#> Baths5 5000.60876 10.27213 486.813 <0.0000000000000002 ***
#> White.Marble1 11503.74939 6.89002 1669.624 <0.0000000000000002 ***
#> Floors1 14995.81772 6.49409 2309.147 <0.0000000000000002 ***
#> City2 3498.29036 7.95420 439.804 <0.0000000000000002 ***
#> City3 6993.49926 7.95549 879.078 <0.0000000000000002 ***
#> Solar1 258.85140 6.49411 39.859 <0.0000000000000002 ***
#> Electric1 1246.96494 6.49405 192.017 <0.0000000000000002 ***
#> Fiber1 11753.39760 6.49413 1809.850 <0.0000000000000002 ***
#> Glass.Doors1 4456.01914 6.49408 686.167 <0.0000000000000002 ***
#> Swiming.Pool1 -1.92964 6.49408 -0.297 0.766
#> Garden1 1.48882 6.49421 0.229 0.819
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 2042 on 395423 degrees of freedom
#> Multiple R-squared: 0.9716, Adjusted R-squared: 0.9716
#> F-statistic: 6.438e+05 on 21 and 395423 DF, p-value: < 0.00000000000000022
- Model dengan Step Wise Regression
model_backward <- step(object = test_model,
direction = "backward",
trace = F)
summary(model_backward)#>
#> Call:
#> lm(formula = Prices ~ Area + Garage + FirePlace + Baths + White.Marble +
#> Floors + City + Solar + Electric + Fiber + Glass.Doors, data = train_house)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -2543.03 -2486.94 0.85 2494.92 2544.55
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 9739.84265 15.09157 645.38 <0.0000000000000002 ***
#> Area 25.01829 0.04522 553.25 <0.0000000000000002 ***
#> Garage2 1501.24244 7.96111 188.57 <0.0000000000000002 ***
#> Garage3 3009.44900 7.95037 378.53 <0.0000000000000002 ***
#> FirePlace1 747.09180 10.28214 72.66 <0.0000000000000002 ***
#> FirePlace2 1488.65166 10.28457 144.75 <0.0000000000000002 ***
#> FirePlace3 2241.73255 10.27297 218.22 <0.0000000000000002 ***
#> FirePlace4 3002.38029 10.27630 292.17 <0.0000000000000002 ***
#> Baths2 1268.65375 10.26935 123.54 <0.0000000000000002 ***
#> Baths3 2499.64345 10.25424 243.77 <0.0000000000000002 ***
#> Baths4 3740.43320 10.26151 364.51 <0.0000000000000002 ***
#> Baths5 5000.60681 10.27209 486.81 <0.0000000000000002 ***
#> White.Marble1 11503.75178 6.89000 1669.63 <0.0000000000000002 ***
#> Floors1 14995.81646 6.49408 2309.15 <0.0000000000000002 ***
#> City2 3498.29098 7.95418 439.81 <0.0000000000000002 ***
#> City3 6993.50374 7.95545 879.08 <0.0000000000000002 ***
#> Solar1 258.84757 6.49404 39.86 <0.0000000000000002 ***
#> Electric1 1246.96589 6.49403 192.02 <0.0000000000000002 ***
#> Fiber1 11753.39126 6.49408 1809.86 <0.0000000000000002 ***
#> Glass.Doors1 4456.02149 6.49402 686.17 <0.0000000000000002 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 2042 on 395425 degrees of freedom
#> Multiple R-squared: 0.9716, Adjusted R-squared: 0.9716
#> F-statistic: 7.115e+05 on 19 and 395425 DF, p-value: < 0.00000000000000022
Rekomendasi Prediktor Step Wise Regression:
Area+Garage+FirePlace+Baths+White.Marble+Floors+City+Solar+Electric+Fiber+Glass.Doors
Pertimbangan Kedua, Kategori Korelasi
- Korelasi Kuat (cor : 0.5 - 0.69):
Floors,Fiber - Korelasi Moderat (cor : 0.30 - 0.49):
white.Marble - Korelasi Lemah (cor : 0.1 - 0.29):
Glass.Doors,City,Electric,Baths,FirePlace,Garage,Area - Tidak Ada Hubungan (cor = 0) :
Garden,Swiming.Pool,Solar
Kita tidak akan menggunakan prediktor yang memiliki korelasi = 0 (tidak ada hubungan).
Rekomendasi Prediktor Berdasarkan Korelasi:
Area+Garage+FirePlace+Baths+White.Marble+Floors+City+Electric+Fiber+Glass.Doors
Final Prediktor
Prediktor yang dipilih berikut : Floors, Fiber, White.Marble, City, Glass.Doors, Baths Electric Garage
Multiple Linear Regression
wt <- 1 / lm(abs(price_sm_model$residuals) ~ price_sm_model$fitted.values)$fitted.values^2
priceHo_multi_model <- lm(formula = Prices ~ Floors + Fiber + White.Marble + City + Glass.Doors + Baths + Electric + Garage, data = train_house, weights = wt)
summary(priceHo_multi_model)#>
#> Call:
#> lm(formula = Prices ~ Floors + Fiber + White.Marble + City +
#> Glass.Doors + Baths + Electric + Garage, data = train_house,
#> weights = wt)
#>
#> Weighted Residuals:
#> Min 1Q Median 3Q Max
#> -0.93665 -0.26899 -0.00013 0.26855 0.93723
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 14492.443 17.101 847.46 <0.0000000000000002 ***
#> Floors1 14992.031 9.294 1613.15 <0.0000000000000002 ***
#> Fiber1 11760.315 9.294 1265.42 <0.0000000000000002 ***
#> White.Marble1 11514.184 9.860 1167.74 <0.0000000000000002 ***
#> City2 3495.719 11.383 307.10 <0.0000000000000002 ***
#> City3 6979.263 11.385 613.02 <0.0000000000000002 ***
#> Glass.Doors1 4452.961 9.294 479.14 <0.0000000000000002 ***
#> Baths2 1273.207 14.696 86.63 <0.0000000000000002 ***
#> Baths3 2497.610 14.675 170.20 <0.0000000000000002 ***
#> Baths4 3739.281 14.685 254.63 <0.0000000000000002 ***
#> Baths5 5001.354 14.700 340.22 <0.0000000000000002 ***
#> Electric1 1251.169 9.293 134.63 <0.0000000000000002 ***
#> Garage2 1504.119 11.393 132.02 <0.0000000000000002 ***
#> Garage3 3008.204 11.378 264.39 <0.0000000000000002 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 0.3768 on 395431 degrees of freedom
#> Multiple R-squared: 0.9418, Adjusted R-squared: 0.9418
#> F-statistic: 4.922e+05 on 13 and 395431 DF, p-value: < 0.00000000000000022
Intrepretasi Model :
- Harga suatu rumah yang terletak di
City1, dengan satuKamar Mandidan memiliki sebuahGarasiadalah 14,492.44 (Berdasarkan nilaiIntercept= 14,492.44). - Cenderung terjadi peningkatan sebesar 14,992.031 apabila rumah menggunakan
lantai Keramik(Berdasarkan nilaiFloors1= 14,992.031). - Cenderung terjadi peningkatan sebesar 11,760.315 apabila rumah menggunakan
Fiber(Berdasarkan nilaiFiber1= 11,760.315). - Cenderung terjadi peningkatan sebesar 11,514.184 apabila rumah menggunakan
White Marble(Berdasarkan nilaiWhite.Marble1= 11,514.184). - Cenderung terjadi peningkatan sebesar 3,495.719 apabila rumah terletak di
City2(Berdasarkan nilaiCity2= 3.495.719). - Cenderung terjadi peningkatan sebesar 6,979.263 apabila rumah terletak di
City3(Berdasarkan nilaiCity3= 6,979.263). - Cenderung terjadi peningkatan sebesar 4,452.961 apabila rumah menggunakan
Glass Door(Berdasarkan nilaiGlass.Doors1= 4452.961). - Cenderung terjadi peningkatan sebesar 1273.207 apabila rumah memiliki 2 buah Kamar Mandi (Berdasarkan nilai
Baths2= 1273.207). - Cenderung terjadi peningkatan sebesar 2497.610 apabila rumah memiliki 3 buah Kamar Mandi (Berdasarkan nilai
Baths3= 2497.610). - Cenderung terjadi peningkatan sebesar 3739.281 apabila rumah memiliki 4 buah Kamar Mandi (Berdasarkan nilai
Baths4= 3739.281). - Cenderung terjadi peningkatan sebesar 5001.354 apabila rumah memiliki 5 buah Kamar Mandi (Berdasarkan nilai
Baths2= 5001.354). - Cenderung terjadi peningkatan sebesar 1251.169 apabila rumah menggunakan
listrik(Berdasarkan nilaiElectric1= 1251.169). - Cenderung terjadi peningkatan sebesar 1504.119 apabila rumah memiliki 2 buah
Garasi(Berdasarkan nilaiGarage2= 1504.119). - Cenderung terjadi peningkatan sebesar 3008.204 apabila rumah memiliki 3 buah
Garasi(Berdasarkan nilaiGarage3= 3008.204).
Model yang kita hasilkan sudah sangat baik. Hal ini terlihat pada semua prediktor yang digunakan memiliki 3 bintang (***) berarti predikornya signifikan.
Prediksi
Kita memprediksi menggunakan data test yang sudah kita pisahkan pada bagian awal modeling.
test_house$y_pred <- predict(object = priceHo_multi_model, newdata = test_house)test_houseKita melihat hasil prediksi model ini cukup beragam, terdapat data yang diprediksi mendekati nilai asli dan juga terdapat data yang diprediksi kurang mendekati nilai asli.
Evaluasi Model
R.Squared
summary(priceHo_multi_model)$adj.r.squared#> [1] 0.9417953
Kesimpulannya, model
priceHo_multi_modelmemiliki goodness of fit alias Adjusted R-squared yang sangat baik yaitu 0.9417953 (mendekati 1).
Error
RMSE(y_pred = test_house$y_pred, y_true = test_house$Prices)#> [1] 2914.388
Interpretasi RMSE: akan terjadi error secara rata-rata sebesar 2914.388 pada setiap poin (titik data) prediksi.
Dalam mengetahui apakah RMSE sudah cukup kecil, biasa kita bandingkan dengan range variable targetnya :
range(test_house$Prices)#> [1] 8275 77525
Dapat disimpulkan error model kita cukup kecil karena rentang data kita cukup besar yaitu (69.250).
Asumsi
1. Normality of Residuals
A. Secara Grafik
residual <- as.data.frame(priceHo_multi_model$residual)
ggplot(data = residual, aes(x = residual$`priceHo_multi_model$residual`)) +
geom_histogram(bins = 10, color="darkblue", fill="lightblue") +
labs(
title = "Persebaran Residual Model",
subtitle = "Setelah Penyesuaian Prediktor",
x = "Residual",
y = "Frekuensi") +
scale_x_continuous(labels = scales::comma) +
scale_y_continuous(labels = scales::comma) +
theme_classic()Terlihat secara grafik relatif error kita berdistribusi normal karena error memusat disekitar 0.
B. Dengan Kolmogorov-Smirnov Test
Uji statistik dengan ks.test()
alpha = 0.05
Kolmogorov-Smirnov hypothesis test:
- H0: error berdistribusi normal (p-value > alpha)
- H1: error TIDAK berdistribusi normal (p-value < alpha)
set.seed(100)
normal_data <- rnorm(priceHo_multi_model$residuals)
ks.test(normal_data, "pnorm")#>
#> Asymptotic one-sample Kolmogorov-Smirnov test
#>
#> data: normal_data
#> D = 0.001523, p-value = 0.3181
#> alternative hypothesis: two-sided
Kesimpulannya gagal tolak H0 karena
p-value > alpha (0.3181 > 0.05)artinya error berdistribusi normal, asumsi terpenuhi.
2. Homoscedasticity of Residuals
A. Secara Grafik
# PErsiapan Dats
set.seed(100)
scatter <- data.frame(X = priceHo_multi_model$fitted.values,
Y = priceHo_multi_model$residuals)
nrow(scatter)#> [1] 395445
# Sampel
index <- sample(nrow(scatter), nrow(scatter)*0.01)
scatter <- scatter[index,]
nrow(scatter)#> [1] 3954
Kita mencoba melihat gambaran penyebaran fitted.values dan residuals. Tetapi kita hanya menggunakan 1% dari keseluruhan agar mempermudah melihat gambaran penyebarannya.
fitted.valuesadalah nilai hasil prediksi data trainingresidualsadalah nilai error (selisih aktual dengan prediksi)
# Visualisasi
ggplot(data = scatter, aes(x = X, y = Y)) +
geom_point() +
labs(
title = "Penyebaran Fitted Values vs Residuals",
subtitle = "Model Multi Linear Regression",
x = "Fitted Values",
y = "Residuals") +
scale_x_continuous(labels = scales::comma) +
scale_y_continuous(labels = scales::comma) +
theme_classic()Terlihat secara grafik relatif error yang dihasilkan menyebar secara acak (tidak berpola) dalam proses pelatihan model.
B. Dengan Breusch-Pagan Test
Uji statistik dengan bptest()
alpha : 0.05
Breusch-Pagan hypothesis test:
- H0: error menyebar konstan atau homoscedasticity (p-value > alpha)
- H1: error menyebar TIDAK konstan atau heteroscedasticity (p-value < alpha)
bptest(priceHo_multi_model)#>
#> studentized Breusch-Pagan test
#>
#> data: priceHo_multi_model
#> BP = 0.003011, df = 13, p-value = 1
Kesimpulannya gagal tolak H0 karena
p-value > alpha (1 > 0.05)artinya error kita menyebar secara acak / tidak berpola (homoscedasticity of residuals), asumsi terpenuhi.
3. No Multicolinearity
Multicollinearity adalah kondisi adanya korelasi antar prediktor yang kuat. Hal ini tidak diinginkan karena menandakan prediktor redundan pada model, yang seharusnya dapat dipilih salah satu saja dari variable yang hubungannya amat kuat tersebut. Harapannya tidak terjadi multicollinearity. Kita menggunakan uji VIF (Variance Inflation Factor) untuk menguji asumsi No Multicolinearity.
Uji VIF dengan fungsi vif()
Variance Inflation Factor hypothesis test:
- nilai VIF atau > 10: terjadi multicollinearity pada model
- nilai VIF < 10: tidak terjadi multicollinearity pada model
vif(priceHo_multi_model)#> GVIF Df GVIF^(1/(2*Df))
#> Floors 1.000032 1 1.000016
#> Fiber 1.000036 1 1.000018
#> White.Marble 1.000035 1 1.000018
#> City 1.000103 2 1.000026
#> Glass.Doors 1.000029 1 1.000015
#> Baths 1.000118 4 1.000015
#> Electric 1.000011 1 1.000006
#> Garage 1.000081 2 1.000020
Berhubung kolom prediktor berjenis factor sehingga kita mengunakan nilai **GVIF^(1/2*Df)** di atas untuk mengantikan nilai VIF yang memang tidak muncul.
Kesimpulannya model kita No Multicollinearity karena setiap predktor memiliki nilai
GVIF^(1/2*Df)kurang dari 10, asumsi terpenuhi.
Kesimpulan
Kita telah melalui berbagai proses dari menyiapkan data hingga membuktikan beberapa asumsi dalam regresi linear. Seluruh keseluruhan kita telah berhasil membangun sebuah model yang dapat digunakan untuk memprediksi harga suatu rumah berdasarkan 9 prediktor yang baik. Model kita juga telah dievaluasi kemudian menghasilkan nilai adj.R-Squared yang sangat tinggi dan nilai error yang relatif kecil dibandingkan range harga.. Model kita juga telah berhasil memenuhi 4 asumsi (satu sebelum pembangunan model dan tiga setelah pembangunan model). Harapannya melalui projek ini dapat menjadi referensi dalam membangun model untuk memprediksi harga suatu rumah. Sekian terima kasih banyak yang telah melihat projek ini. Saya juga menyukai masukan dan kolaborasi sehingga apabila ada masukan, saran atau untuk berkolaborasi dapat menghubungi lewat Linkedin.